package com.demo.small_tool.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.demo.small_tool.dto.ReqDTO;
import com.demo.small_tool.response.Resp;
import com.demo.small_tool.dto.Detail;
import com.demo.small_tool.dto.RespDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api")
@Slf4j
public class HttpController {

    @PostMapping("/send")
    @ResponseBody
    public Resp<RespDTO> postReq(@Valid @RequestBody ReqDTO reqDTO) {
        try {
            Map<String, String> headers = parseHeaders(reqDTO.getHeader());
            String body = buildBody(reqDTO);
            String getUrl = buildGetUrl(reqDTO, body);

            RespDTO respDTO = new RespDTO();
            HttpResponse response;
            String method = reqDTO.getMethod() == null ? "POST" : reqDTO.getMethod().toUpperCase();
            switch (method) {
                case "POST":
                    response = postRequest(reqDTO, body, headers);
                    break;
                case "GET":
                    response = getRequest(getUrl);
                    break;
                default:
                    return Resp.fail("400", "不支持的请求方法: " + method, "");
            }
            respDTO.setBody(StringEscapeUtils.unescapeJava(response.body()));
            respDTO.setHttpCode(response.getStatus());
            respDTO.setHeader(response.header(Header.CONTENT_TYPE));
            Detail detail = new Detail();
            detail.setHttp_code(response.getStatus());
            detail.setUrl(reqDTO.getUrl());
            respDTO.setDetail(detail);
            log.info("post请求结果：{}", JSONUtil.toJsonStr(respDTO));
            return Resp.success("200", "success", respDTO);
        } catch (IllegalArgumentException e) {
            log.error("参数错误", e);
            return Resp.fail("400", "参数错误", e.getMessage());
        } catch (Exception e) {
            log.error("请求处理异常", e);
            return Resp.fail("500", "请求处理异常", e.getMessage());
        }
    }

    /**
     * 解析header字符串为Map
     */
    private Map<String, String> parseHeaders(String headerStr) {
        if (StrUtil.isEmpty(headerStr)) {
            return Collections.singletonMap("Content-Type", "application/json");
        }
        Map<String, String> headers = new HashMap<>();
        headerStr = headerStr.replaceAll("\n", "");
        String[] headerSplit = headerStr.split(";");
        for (String s : headerSplit) {
            if (StrUtil.isBlank(s)) continue;
            String[] headerArr = s.split(":", 2);
            if (headerArr.length != 2) {
                throw new IllegalArgumentException("header格式错误，应为key:value");
            }
            headers.put(headerArr[0].trim(), headerArr[1].trim());
        }
        return headers;
    }

    /**
     * 构建请求体
     */
    private String buildBody(ReqDTO reqDTO) {
        if (StrUtil.isEmpty(reqDTO.getBody())) {
            return "";
        }
        String dtoBody = reqDTO.getBody();
        JSONObject xmlToJson = JSONUtil.xmlToJson(dtoBody);
        boolean json = JSONUtil.isJson(JSONUtil.toJsonStr(xmlToJson));
        boolean isXmlToJson = !xmlToJson.isEmpty() && json;
        if (JSONUtil.isJson(dtoBody) || isXmlToJson) {
            return dtoBody;
        }
        return dtoBody;
    }

    /**
     * 构建GET请求的url
     */
    private String buildGetUrl(ReqDTO reqDTO, String body) {
        String getUrl = reqDTO.getUrl();
        if (StrUtil.isNotEmpty(body) && (body.contains("&") || body.contains("="))) {
            getUrl += getUrl.contains("?") ? "&" + body : "?" + body;
        }
        return getUrl;
    }

    public HttpResponse getRequest(String url) {
        return HttpUtil.createGet(url)
                .execute(true);
    }

    public HttpResponse postRequest(ReqDTO reqDTO, String body, Map<String, String> headers) {
        return HttpUtil.createPost(reqDTO.getUrl())
                .body(body)
                .addHeaders(headers)
                .cookie(reqDTO.getCookie())
                .execute(true);
    }
}
